using System;
using System.Collections.Generic;
using Cysharp.Threading.Tasks;
using Shared.UI;
using UnityEngine;

namespace Framework.UI
{
    /*
     * 界面基类
     */
    public class UIController : IDisposable
    {
        public Enum Id;
        public GameObject Target;
        public Transform Layer;
        public List<UIController> Childrens;
        public UIArg Args;
        public string ResDir;

        public UIController()
        {
            Childrens = new List<UIController>();
        }

        public bool IsValid => Target != null;
        public Transform Transform => IsValid ? Target.transform : null;
        public bool Actived => IsValid && Target.activeSelf;

        public void SetArgs(Enum id, UIArg args)
        {
            Id = id;
            Args = args;
        }

        protected virtual async UniTask RequestProtocol()
        {
            await UniTask.CompletedTask;
        }

        public async UniTask OnOpen()
        {
            await RequestProtocol();
            await AddListeners();
            Childrens.Clear();
            await OnRefreshUI();
            
            SetActive(true);
        }

        public async UniTask OnReopen()
        {
            await ActiveChildren(true);
            
            SetActive(true);
        }

        public async UniTask OnPause()
        {
            SetActive(false);
            
            await ActiveChildren(false);
        }

        public async UniTask OnClose()
        {
            await RemoveListeners();
            await RemoveChildren();
            Args = null;
            
            SetActive(false);
        }

        public async UniTask<T> Active<T>(Enum id) where T : UIController, new()
        {
            return await UIManager.Instance.Active<T>(id);
        }

        public async UniTask Deactive(Enum id = null)
        {
            id = id ?? Id;
            await UIManager.Instance.Deactive(id);
        }

        public void AddChild(UIController child)
        {
            if (!IsValid)
                return;
            
            if (Childrens == null)
                return;
            
            if (!Childrens.Contains(child))
                Childrens.Add(child);
        }

        public void RemoveChild(UIController child)
        {
            if (!IsValid)
                return;

            if (Childrens.Contains(child))
                Childrens.Remove(child);
        }
        
        public void SetLayer(Transform layer)
        {
            if (!IsValid)
                return;
            
            if (layer == null)
            {
                Debug.LogError($"layer want to set is null.");
                return;
            }
            
            if (Layer != null && Layer.Equals(layer))
                return;
            
            Layer = layer;
            
            Target.transform.SetParent(Layer, false);
        }

        private void SetActive(bool active)
        {
            if (!IsValid)
                return;
            
            if (Actived == active)
                return;
            
            Target.SetActive(active);
        }

        protected virtual async UniTask AddListeners()
        {
            await UniTask.CompletedTask;
        }

        protected virtual async UniTask RemoveListeners()
        {
            await UniTask.CompletedTask;
        }

        protected virtual async UniTask OnRefreshUI()
        {
            if (!IsValid)
                return;

            UIView view = Target.GetComponent<UIView>();
            if (view != null)
            {
                await view.RefreshUI();
            }
            
            await UniTask.CompletedTask;
        }

        public virtual async void Dispose()
        {
            await UniTask.CompletedTask;
        }

        public async UniTask Destroy()
        {
            Dispose();
            await OnClose();
            if (IsValid)
            {
                UnityEngine.Object.Destroy(Target);
                Target = null;
            }
        }

        private async UniTask ActiveChildren(bool active)
        {
            if (Childrens.Count <= 0)
                return;

            for (int i = 0; i < Childrens.Count; i++)
            {
                if (active)
                    await Childrens[i].OnOpen();
                else
                    await Childrens[i].OnClose();
            }
        }

        private async UniTask RemoveChildren()
        {
            if (Childrens.Count <= 0)
                return;

            for (int i = 0; i < Childrens.Count; i++)
            {
                await Childrens[i].OnClose();
            }

            Childrens.Clear();
        }
    }
}